﻿using SnailInfo.ConvertExtension.Enums;
using System.Globalization;
using System.Runtime.CompilerServices;

/********************************************
* 公司名称：snail information
* 创 建 人：cfhknight
* 创建日期：2025/9/29 13:09:12
* 说    明：date time extentions
* 版    本：V0.0.0.1
********************************************/
namespace SnailInfo.ConvertExtension
{
    public static class TimeExtension
    {
        private static HashSet<string> format = new HashSet<string>();
        private const long TicksPerMicrosecond = 10;
        private const long TicksPerMillisecond = TicksPerMicrosecond * 1000;
        const long TicksPerSecond = TicksPerMillisecond * 1000;
        static TimeExtension()
        {
            format.Add("yyyy-MM-dd HH:mm:ss");
            format.Add("yyyy-MM-dd");
            format.Add("yyyy.MM.dd");
            format.Add("yyyy/MM/dd");
        }
        /// <summary>
        /// convert to datetime
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        public static DateTime ToDateTime(string value)
        {
            if (string.IsNullOrWhiteSpace(value)) {
                throw new ArgumentException($"the value of {value} can not be convert datetime !");
            }
            var isDatetimeType = DateTime.TryParse(value, out DateTime result);
            if (isDatetimeType) {
                return result;
            }
            throw new ArgumentException($"the value of {value} can not be convert datetime !");
        }
        /// <summary>
        /// convert string to datetime with the format
        /// </summary>
        /// <param name="value"></param>
        /// <param name="format"></param>
        /// <returns></returns>
        public static DateTime ToDateTime(this string value, string format)
        {
            if (DateTime.TryParseExact(value, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime result)) {
                return result;
            } else {
                throw new ArgumentException($"the value of {value} can not be convert datetime by format string of {format} ");
            }

        }
        /// <summary>
        /// get start time of the date,will return yyyy.MM.dd 00:00:00.000
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static DateTime ToStartTime(this DateTime value)
        {
            return new DateTime(value.Year, value.Month, value.Day, 0, 0, 0, 0);
        }
        /// <summary>
        /// get the end time of the date , will return yyyy.MM.dd 23:59:59.999
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static DateTime ToEndTime(this DateTime value)
        {
            return new DateTime(value.Year, value.Month, value.Day, 23, 59, 59, 999);
        }
        /// <summary>
        /// convert to timestamp of millisecond by datetime
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static long ToTimeStamp(this DateTime value)
        {
            var offset = new DateTimeOffset(value.ToUniversalTime());
            long result;
            long ticks = value.ToUniversalTime().Ticks;
            var unixEpochTicks = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).Ticks;
            result = (ticks - unixEpochTicks) / TicksPerMillisecond;
            Console.WriteLine(result);
            return result;
        }
        /// <summary>
        /// convert timestamp of stamp enum by datetime
        /// </summary>
        /// <param name="value"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static long ToTimeStamp(this DateTime value, TimeStampEnum type)
        {
            var offset = new DateTimeOffset(value.ToUniversalTime());
            switch (type) {
                case TimeStampEnum.Millisecond:
                    return value.ToTimeStamp();
                case TimeStampEnum.Second:
                    long result;
#if NET45
                     long ticks = value.ToUniversalTime().Ticks;
                    var unixEpochTicks = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).Ticks;
                    result = (ticks - unixEpochTicks) / TicksPerSecond;
#elif NET
                    result = offset.ToUnixTimeSeconds();
#else
                    throw new Exception("Not Support platform");
#endif

                    return result;
                default:
                    return value.ToTimeStamp();
            }
        }
        /// <summary>
        /// Convert to week of year from datetime
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static int ToWeekOfYear(this DateTime time)
        {
            DateTime date = Convert.ToDateTime(time.ToString("yyyy") + "-01-01");
            TimeSpan ts = Convert.ToDateTime(time.ToString("yyyy-MM-dd")) - date;
            int iDays = (int)time.DayOfWeek;
            int iDay = int.Parse(ts.TotalDays.ToString("F0"));
            if (iDays == 0) {
                iDay--;
            } else {
                iDay = iDay - (7 - iDays) - 1;
            }

            return ((iDay + 7) / 7) + 1;
        }
    }
}
